import {_decorator, Component, instantiate, Prefab, resources} from 'cc';
import {BlockType} from "db://assets/scripts/object/BlockType";
import {GameState} from "db://assets/scripts/common/GameState";
import {EventManager} from "db://assets/scripts/common/EventManager";
import {EventType} from "db://assets/scripts/common/EventType";

const {ccclass, property} = _decorator;

/**
 * 游戏管理器
 */
@ccclass('GameManager')
export class GameManager extends Component {
    /**
     * 当前游戏状态
     */
    private currentGameState: GameState;
    /**
     * 路是由多个块组成，而每个块有可能是坑，也有可能是实地
     */
    private road: BlockType[] = [];
    /**
     * 路的长度
     */
    private roadLength: number = 100;

    onEnable() {
        // 系统事件

        // 自定义事件
        EventManager.on(EventType.START_GAME, this.startGame, this);
        EventManager.on(EventType.CHECK_GAME_IS_OVER, this.checkGameIsOver, this);
        EventManager.on(EventType.GAME_OVER, this.gameOver, this);
    }

    onDisable() {
        // 系统事件

        // 自定义事件
        EventManager.off(EventType.START_GAME, this.startGame, this);
        EventManager.off(EventType.CHECK_GAME_IS_OVER, this.checkGameIsOver, this);
        EventManager.off(EventType.GAME_OVER, this.gameOver, this);
    }

    /**
     * 开始游戏
     *
     * @link EventType.START_GAME
     */
    private startGame() {
        this.setCurrentGameState(GameState.PLAYING);
    }

    /**
     * 检查游戏是否结束
     *
     * @param step 当前步长
     * @link EventType.CHECK_GAME_IS_OVER
     */
    private checkGameIsOver(step: number) {
        // 更新步数
        EventManager.dispatchEvent(EventType.UI_STEP_SET_STEP, step);

        // 当踩到坑时
        if (this.road[step] === BlockType.NONE) {
            console.log("游戏失败！！！");
            this.setCurrentGameState(GameState.END);
            return;
        }

        // 当步长超过路长时
        if (step > this.roadLength) {
            console.log("游戏胜利！！！");
            this.setCurrentGameState(GameState.END);
        }
    }

    /**
     * 游戏结束
     *
     * @link EventType.GAME_OVER
     */
    private gameOver() {
        console.log("游戏结束");
        this.setCurrentGameState(GameState.END);
    }

    start() {
        // 初始化
        this.setCurrentGameState(GameState.INIT);
    }

    /**
     * 设置游戏状态
     *
     * @param gameState 游戏状态
     */
    private setCurrentGameState(gameState: GameState) {
        this.currentGameState = gameState;
        switch (gameState) {
            case GameState.INIT:
                this.init();
                break;
            case GameState.PLAYING:
                // 隐藏开始菜单
                EventManager.dispatchEvent(EventType.UI_START_MENU_VISIBLE, false);
                // 将分数重置为0
                EventManager.dispatchEvent(EventType.UI_STEP_SET_STEP, 0);

                // 设置 active 为 true 时会直接开始监听鼠标事件，此时鼠标抬起事件还未派发
                // 会出现的现象就是，游戏开始的瞬间人物已经开始移动
                // 因此，这里需要做延迟处理
                setTimeout(() => {
                    EventManager.dispatchEvent(EventType.PLAYER_ENABLE_MOUSE_UP, true);
                }, 1000);
                break;
            case GameState.END:
                break;
        }
    }

    /**
     * 初始化
     */
    private init() {
        // 显示游戏菜单
        EventManager.dispatchEvent(EventType.UI_START_MENU_VISIBLE, true);

        // 初始化瓦片预制体
        resources.load("prefab/tile", Prefab, (err: Error, prefab: Prefab) => {
            if (err) {
                console.log("地砖初始化失败！！！");
                return;
            }
            // 生成路
            this.generateRoad(prefab);
        });

        // 发送禁止玩家接收鼠标事件
        EventManager.dispatchEvent(EventType.PLAYER_ENABLE_MOUSE_UP, false);
    }

    /**
     * 生成路
     *
     * @param tilePrefab 实地预制体
     */
    private generateRoad(tilePrefab: Prefab) {
        // 防止游戏重新开始时，赛道还是旧的赛道
        // 因此，需要移除旧赛道，清除旧赛道数据
        this.clearRoad();

        // 确保角色能够站立，第一块必须是实地
        this.road.push(BlockType.STONE);

        // 确定每一格赛道类型
        for (let i = 1; i < this.roadLength; i++) {
            // 如果上一格赛道是坑，那么这一格一定不能为坑
            if (this.road[i - 1] === BlockType.NONE) {
                this.road.push(BlockType.STONE);
            } else {
                // 随机
                this.road.push(Math.random() > 0.5 ? BlockType.STONE : BlockType.NONE);
            }
        }

        // 根据赛道类型生成赛道
        for (let i = 0; i < this.roadLength; i++) {
            if (this.road[i] === BlockType.STONE) {
                // 根据实地预制体创建实地节点
                let titleNode = instantiate(tilePrefab);
                // 配置相关参数
                titleNode.setPosition(i, -1.5, 0);

                // 添加到路节点下
                this.node.addChild(titleNode);
            }
        }
    }

    /**
     * 清除赛道
     */
    private clearRoad() {
        this.road = [];
        this.node.removeAllChildren();
    }

    update(deltaTime: number) {

    }
}

